
// ================================================================================================
// -*- C++ -*-
// File: WorldState.hpp
// Author: Guilherme R. Lampert
// Created on: 16/09/13
// Brief: State of the Ants world this turn.
// ================================================================================================

#ifndef __WORLDSTATE_HPP__
#define __WORLDSTATE_HPP__

// STD C++ includes:
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <iostream>
#include <string>
#include <list>
#include <vector>
#include <cassert>

// Local includes:
#include "Debug.hpp"
#include "MapCell.hpp"
#include "Ant.hpp"

// Graph search helpers:
#include "Graph.hpp"
#include "DijkstrasSearch.hpp"

// Termination condition used by the Dijkstra's search algorithm.
// Stops the search when a path to a node containing food, enemy ant or enemy hill is found.
class TermCondInterestingItemFound {
public:

	template<class GraphType>
	static bool IsSatisfied(const GraphType & graph, int targetNode, int currentNode)
	{
		(void)targetNode; // Not used

		const typename GraphType::NodeType & node = graph.GetNode(currentNode);
		const MapCell & cell = *node.cell;

		// Chase food:
		if (CellIsFood(cell))
		{
			return (true);
		}

		// Chase enemy ants an hills:
		if (CellIsAnt(cell) || CellIsAntHill(cell))
		{
			if (cell.player != 0) // Player 0 is me
			{
				return (true);
			}
		}

		return (false);
	}
};

// Game startup parameters:
struct StartupParameters {

	// Random seed used:
	INT_64 playerSeed;

	// Turn counter:
	int numTurns;

	// Rows x columns in the map:
	int mapRows;
	int mapCols;

	// Times:
	double loadTime;
	double turnTime;

	// View radius:
	double viewRadiusSquared;
	double viewRadius;

	// Attack radius:
	double attackRadiusSquared;
	double attackRadius;

	// Spawn radius:
	double spawnRadiusSquared;
	double spawnRadius;
};

// World state. Updated every turn.
class WorldState {

public:

	WorldState(const StartupParameters * startupParams);
	~WorldState();

	void Update();
	bool GameOver() const;

	// Map extents. Map starts at (0,0).
	inline int MaxMapX() const { return (params->mapCols); }
	inline int MaxMapY() const { return (params->mapRows); }

	// Map cell access. Always use this to access the map,
	// since it checks for out-of-bounds errors with assert().
	MapCell & MapCellAt(int x, int y) const;

	// Get a given node from the search graph.
	inline const GraphNode & GetGraphNode(int index) const { return (searchGraph.GetNode(index)); }

	// Read new game state (input):
	friend std::istream & operator >> (std::istream & is, WorldState & state);

private:

	// Makes our moves.
	void MakeMoves();

	// Ends out turn.
	void EndTurn();

	// Dump current map for debugging.
	void DebugDump() const;

	// Ant list updates:
	void UpdateAliveAnt(int x, int y);
	void UpdateDeadAnt(int x, int y);

	// Sets up the search graph and its edges.
	void SetupSearchGraph();

	// Build graph edges.
	void BuildEdges();

private:

	// Set when we get an 'end' message from the input.
	bool gameOver;

	// This turns number.
	int turnNum;

	// Number of players still in the game.
	int numPlayers;

	// 'params' is just a reference to an object owned by AntCommander.
	const StartupParameters * params;

	// Map grid as a linear array (use x + y * width to index a given cell):
	MapCell * map;

	// Ants we own:
	typedef std::list<Ant> AntList;
	AntList myAnts;

	// Graph used for advanced goal searching.
	// Every cell in the map is a graph node.
	typedef SparseGraph<GraphNode, GraphEdge> MyGraph;
	MyGraph searchGraph;

	// Search algorithm. Since we search for items such as food,
	// which is abundant in the map, Dijkstra's search is a better choice than A-Star.
	DijkstrasSearch<MyGraph, TermCondInterestingItemFound> searchAlgorithm;
};

#endif // __WORLDSTATE_HPP__
